/*******************************************************************************
 * Copyright (c) 2004 Actuate Corporation.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * https://www.eclipse.org/legal/epl-2.0/.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 *
 * Contributors:
 *  Actuate Corporation  - initial API and implementation
 *******************************************************************************/

package org.eclipse.birt.report.designer.util;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import org.eclipse.birt.core.data.ExpressionUtil;
import org.eclipse.birt.core.format.DateFormatter;
import org.eclipse.birt.core.internal.util.EclipseUtil;
import org.eclipse.birt.report.designer.core.DesignerConstants;
import org.eclipse.birt.report.designer.core.IReportElementConstants;
import org.eclipse.birt.report.designer.core.model.SessionHandleAdapter;
import org.eclipse.birt.report.designer.core.model.views.data.DataSetItemModel;
import org.eclipse.birt.report.model.api.AbstractThemeHandle;
import org.eclipse.birt.report.model.api.ActionHandle;
import org.eclipse.birt.report.model.api.CellHandle;
import org.eclipse.birt.report.model.api.ComputedColumnHandle;
import org.eclipse.birt.report.model.api.ContentElementHandle;
import org.eclipse.birt.report.model.api.DataItemHandle;
import org.eclipse.birt.report.model.api.DataSetHandle;
import org.eclipse.birt.report.model.api.DataSetParameterHandle;
import org.eclipse.birt.report.model.api.DataSourceHandle;
import org.eclipse.birt.report.model.api.DesignConfig;
import org.eclipse.birt.report.model.api.DesignElementHandle;
import org.eclipse.birt.report.model.api.DesignEngine;
import org.eclipse.birt.report.model.api.DesignFileException;
import org.eclipse.birt.report.model.api.DimensionHandle;
import org.eclipse.birt.report.model.api.GraphicMasterPageHandle;
import org.eclipse.birt.report.model.api.GridHandle;
import org.eclipse.birt.report.model.api.GroupElementFactory;
import org.eclipse.birt.report.model.api.GroupElementHandle;
import org.eclipse.birt.report.model.api.GroupHandle;
import org.eclipse.birt.report.model.api.IResourceLocator;
import org.eclipse.birt.report.model.api.ImageHandle;
import org.eclipse.birt.report.model.api.LabelHandle;
import org.eclipse.birt.report.model.api.LevelAttributeHandle;
import org.eclipse.birt.report.model.api.LibraryHandle;
import org.eclipse.birt.report.model.api.ListingHandle;
import org.eclipse.birt.report.model.api.ModuleHandle;
import org.eclipse.birt.report.model.api.ParameterGroupHandle;
import org.eclipse.birt.report.model.api.ParameterHandle;
import org.eclipse.birt.report.model.api.PropertyHandle;
import org.eclipse.birt.report.model.api.ReportDesignHandle;
import org.eclipse.birt.report.model.api.ReportElementHandle;
import org.eclipse.birt.report.model.api.ReportItemHandle;
import org.eclipse.birt.report.model.api.ReportItemHandleImpl;
import org.eclipse.birt.report.model.api.ReportItemThemeHandle;
import org.eclipse.birt.report.model.api.ResultSetColumnHandle;
import org.eclipse.birt.report.model.api.RowHandle;
import org.eclipse.birt.report.model.api.SlotHandle;
import org.eclipse.birt.report.model.api.StyleHandle;
import org.eclipse.birt.report.model.api.TableHandle;
import org.eclipse.birt.report.model.api.ThemeHandle;
import org.eclipse.birt.report.model.api.VariableElementHandle;
import org.eclipse.birt.report.model.api.activity.SemanticException;
import org.eclipse.birt.report.model.api.core.IAccessControl;
import org.eclipse.birt.report.model.api.core.IDesignElement;
import org.eclipse.birt.report.model.api.core.IModuleModel;
import org.eclipse.birt.report.model.api.elements.DesignChoiceConstants;
import org.eclipse.birt.report.model.api.elements.ReportDesignConstants;
import org.eclipse.birt.report.model.api.elements.structures.Action;
import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn;
import org.eclipse.birt.report.model.api.metadata.DimensionValue;
import org.eclipse.birt.report.model.api.metadata.IArgumentInfo;
import org.eclipse.birt.report.model.api.metadata.IArgumentInfoList;
import org.eclipse.birt.report.model.api.metadata.IClassInfo;
import org.eclipse.birt.report.model.api.metadata.IElementDefn;
import org.eclipse.birt.report.model.api.metadata.IElementPropertyDefn;
import org.eclipse.birt.report.model.api.metadata.IMemberInfo;
import org.eclipse.birt.report.model.api.metadata.IMetaDataDictionary;
import org.eclipse.birt.report.model.api.metadata.IMethodInfo;
import org.eclipse.birt.report.model.api.metadata.IPropertyDefn;
import org.eclipse.birt.report.model.api.metadata.ISlotDefn;
import org.eclipse.birt.report.model.api.olap.LevelHandle;
import org.eclipse.birt.report.model.api.olap.MeasureHandle;
import org.eclipse.birt.report.model.api.util.ColorUtil;
import org.eclipse.birt.report.model.api.util.DimensionUtil;
import org.eclipse.birt.report.model.api.util.StringUtil;
import org.eclipse.birt.report.model.api.util.URIUtil;
import org.eclipse.birt.report.model.elements.interfaces.IAbstractThemeModel;
import org.eclipse.birt.report.model.elements.interfaces.ICellModel;
import org.eclipse.birt.report.model.elements.interfaces.IGraphicMaterPageModel;
import org.eclipse.birt.report.model.elements.interfaces.IGridItemModel;
import org.eclipse.birt.report.model.elements.interfaces.IInternalReportDesignModel;
import org.eclipse.birt.report.model.elements.interfaces.ILabelModel;
import org.eclipse.birt.report.model.elements.interfaces.IParameterGroupModel;
import org.eclipse.birt.report.model.elements.interfaces.IStyleModel;
import org.eclipse.birt.report.model.elements.interfaces.ITableRowModel;
import org.eclipse.birt.report.model.elements.interfaces.ITextItemModel;
import org.eclipse.birt.report.model.metadata.ElementPropertyDefn;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;

import com.ibm.icu.text.Collator;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;

/**
 * This class integrated some methods that will be used in GUI. It provides the
 * information that GUI will use and is called widely. *
 */
public class DEUtil {

	/**
	 * Property name for element labelContent.
	 */
	public static final String ELEMENT_LABELCONTENT_PROPERTY = "labelContent"; //$NON-NLS-1$

	private static HashMap<String, String> propertiesMap = new HashMap<>();

	private static ArrayList<IElementDefn> notSupportList = new ArrayList<>();

	private static int defaultFontSite = -1;

	private static List<String> scalable_system_fonts = null;

	private static List<String> non_scalable_system_fonts = null;

	private static volatile String[] sorted_system_fonts = null;

	private static final DesignEngine designEngine = new DesignEngine(new DesignConfig());

	private static final String XMLDATE_PATTERN_FULL = "yyyy-MM-dd'T'HH:mm:ss.SSS"; //$NON-NLS-1$
	private static final String XMLDATE_PATTERN_DATE_ONLY = "yyyy-MM-dd"; //$NON-NLS-1$
	private static final String XMLDATE_PATTERN_WITH_OUT_SECOND = "yyyy-MM-dd'T'HH:mm"; //$NON-NLS-1$
	private static final String XMLDATE_PATTERN_WITH_OUT_MILLISECOND = "yyyy-MM-dd'T'HH:mm:ss"; //$NON-NLS-1$
	/** property: default library */
	public static final String DEFAULT_LIBRARY = "/ThemesReportItems31.rptlibrary"; //$NON-NLS-1$
	private static List<String> paletteElementList = new ArrayList<>();

	/**
	 * The class info of total
	 */
	public static final IClassInfo TOTAL_CLASS = getMetaDataDictionary().getClass(IMetaDataDictionary.TOTAL_CLASS_NAME);

	static {
		propertiesMap.put(ILabelModel.TEXT_PROP, ELEMENT_LABELCONTENT_PROPERTY);
		propertiesMap.put(ITextItemModel.CONTENT_PROP, ELEMENT_LABELCONTENT_PROPERTY);

		// do not support following element in release 2
		notSupportList.add(getMetaDataDictionary().getElement(ReportDesignConstants.LINE_ITEM));
		notSupportList.add(getMetaDataDictionary().getElement(ReportDesignConstants.TEMPLATE_REPORT_ITEM));
		notSupportList.add(getMetaDataDictionary().getElement(ReportDesignConstants.FREE_FORM_ITEM));
		notSupportList.add(getMetaDataDictionary().getElement(ReportDesignConstants.GRAPHIC_MASTER_PAGE_ELEMENT));

		// filter generic Extended item and AutoText item.
		notSupportList.add(getMetaDataDictionary().getElement(ReportDesignConstants.AUTOTEXT_ITEM));
		notSupportList.add(getMetaDataDictionary().getElement(ReportDesignConstants.EXTENDED_ITEM));

		paletteElementList.add(IReportElementConstants.REPORT_ELEMENT_LABEL);
		paletteElementList.add(IReportElementConstants.REPORT_ELEMENT_TEXT);
		paletteElementList.add(IReportElementConstants.REPORT_ELEMENT_TEXTDATA);
		paletteElementList.add(IReportElementConstants.REPORT_ELEMENT_DATA);
		paletteElementList.add(IReportElementConstants.REPORT_ELEMENT_IMAGE);
		paletteElementList.add(IReportElementConstants.REPORT_ELEMENT_GRID);
		paletteElementList.add(IReportElementConstants.REPORT_ELEMENT_LIST);
		paletteElementList.add(IReportElementConstants.REPORT_ELEMENT_TABLE);
	}

	/**
	 * Gets the support list of the given parent element and the slotID.
	 *
	 * Note: this method returns all supported elements including invisible ones
	 * from UI. To get supported UI element list, check
	 * {@link UIUtil#getUIElementSupportList()}
	 *
	 * @param parent the parent element
	 * @param slotId the slotID
	 * @return the element list that is supported with the given parent element and
	 *         in the given slotID
	 */
	public static List<IElementDefn> getElementSupportList(DesignElementHandle parent, int slotId) {
		List<IElementDefn> list = new ArrayList<>();
		ISlotDefn slotDefn = parent.getDefn().getSlot(slotId);
		if (slotDefn != null) {
			list.addAll(slotDefn.getContentExtendedElements());
			list.removeAll(notSupportList);
		}

		// Append to validate the type according to the context
		List<IElementDefn> availableList = new ArrayList<>();
		List<IElementDefn> extendedList = new ArrayList<>();
		for (IElementDefn elementDefn : list) {
			if (parent.canContain(slotId, elementDefn.getName())) {
				if (elementDefn.isExtendedElement()) {
					extendedList.add(elementDefn);
				} else {
					availableList.add(elementDefn);
				}
			}
		}
		Collections.sort(availableList, new Comparator<IElementDefn>() {

			@Override
			public int compare(IElementDefn o1, IElementDefn o2) {
				return paletteElementList.indexOf(o1.getName()) - paletteElementList.indexOf(o2.getName());
			}
		});
		Collections.sort(extendedList, new Comparator<IElementDefn>() {

			@Override
			public int compare(IElementDefn o1, IElementDefn o2) {
				return Collator.getInstance().compare(o1.getName(), o2.getName());
			}
		});
		availableList.addAll(extendedList);
		return availableList;
	}

	/**
	 * Get the containable element type list of give slot handle.
	 *
	 * Note: this method returns all supported elements including invisible ones
	 * from UI. To get supported UI element list, check
	 * {@link UIUtil#getUIElementSupportList()}
	 *
	 * @param slotHandle
	 * @return Return the containable element type list of give slot handle.
	 */
	public static List<IElementDefn> getElementSupportList(SlotHandle slotHandle) {
		return getElementSupportList(slotHandle.getElementHandle(), slotHandle.getSlotID());
	}

	/**
	 * Gets the support list of the given property handle.
	 *
	 * Note: this method returns all supported elements including invisible ones
	 * from UI. To get supported UI element list, check
	 * {@link UIUtil#getUIElementSupportList(PropertyHandle propertyHandle)}
	 *
	 * @param propertyHandle
	 * @return Return the support list of the given property handle.
	 */
	public static List<IElementDefn> getElementSupportList(PropertyHandle propertyHandle) {
		List<IElementDefn> list = new ArrayList<>();
		IPropertyDefn propertyDefn = propertyHandle.getPropertyDefn();
		if (propertyDefn != null) {
			list.addAll(propertyDefn.getAllowedElements(true));
			list.removeAll(notSupportList);
		}

		// Append to validate the type according to the context
		List<IElementDefn> availableList = new ArrayList<>();
		List<IElementDefn> extendedList = new ArrayList<>();
		for (IElementDefn elementDefn : list) {
			if (propertyHandle.canContain(elementDefn.getName())) {
				if (elementDefn.isExtendedElement()) {
					extendedList.add(elementDefn);
				} else {
					availableList.add(elementDefn);
				}
			}
		}
		Collections.sort(availableList, new Comparator<IElementDefn>() {

			@Override
			public int compare(IElementDefn o1, IElementDefn o2) {
				return paletteElementList.indexOf(o1.getName()) - paletteElementList.indexOf(o2.getName());
			}
		});
		Collections.sort(extendedList, new Comparator<IElementDefn>() {

			@Override
			public int compare(IElementDefn o1, IElementDefn o2) {
				return Collator.getInstance().compare(o1.getName(), o2.getName());
			}
		});
		availableList.addAll(extendedList);
		return availableList;
	}

	/**
	 * Find the position of the element. If the element is null, the position is
	 * last
	 *
	 * @param parent  parent element
	 * @param element element to be searched
	 * @param slotID  slot id to be started
	 * @return the position of the element
	 */
	public static int findInsertPosition(DesignElementHandle parent, DesignElementHandle element, int slotID) {
		if (element == null) {
			SlotHandle slotHandle = parent.getSlot(slotID);
			if (slotHandle != null) {
				return slotHandle.getCount();
			}
			return -1;
		}
		return DEUtil.findPos(parent, slotID, element);
	}

	/**
	 * Find the position of the element. If the element is null, the position is
	 * last
	 *
	 * @param parent  parent element
	 * @param element element to be searched
	 * @param content content where is to search
	 * @return Return the position of the element
	 */
	public static int findInsertPosition(DesignElementHandle parent, DesignElementHandle element, String content) {
		if (element == null) {
			return parent.getContentCount(content);
		}
		return element.getIndex();
	}

	/**
	 * Finds the position of the child element in the parent element with the given
	 * slotID
	 *
	 * @param parent the parent element
	 * @param slotID the slotID
	 * @param child  the child element
	 * @return the position of the child element
	 */

	public static int findPos(DesignElementHandle parent, int slotID, DesignElementHandle child) {
		assert slotID >= 0;
		SlotHandle slotHandle = parent.getSlot(slotID);
		return slotHandle.findPosn(child);
	}

	/**
	 * Gets the element name. The object is a long string that separated with the
	 * separator "."
	 *
	 * @param obj the object
	 * @return the name behind the last separator "."
	 */

	public static String getElementName(Object obj) {
		if (obj instanceof Class) {
			obj = ((Class) obj).getName();
		}
		return obj.toString().substring(obj.toString().lastIndexOf(".") + 1); //$NON-NLS-1$
	}

	/**
	 * Gets the definition for the element with the specified name
	 *
	 * @param elementName the name of the element
	 *
	 * @return Returns the definition, or null if the element is not defined.
	 */
	public static IElementDefn getElementDefn(String elementName) {
		IElementDefn defn = getMetaDataDictionary().getElement(elementName);
		if (defn == null) {
			defn = getMetaDataDictionary().getExtension(elementName);
		}
		return defn;
	}

	/**
	 * Get display label of report element
	 *
	 * @param obj
	 * @return Return the display label of report element
	 */
	public static String getDisplayLabel(Object obj) {
		return getDisplayLabel(obj, true);
	}

	/**
	 * Get display label of report element
	 *
	 * @param obj
	 * @param includeElementName
	 * @return Return the display label of report element
	 */
	public static String getDisplayLabel(Object obj, boolean includeElementName) {
		if (obj instanceof DesignElementHandle) {
			DesignElementHandle handle = (DesignElementHandle) obj;
			String elementName = handle.getDefn().getDisplayName();
			String displayName;
			if (handle.getQualifiedName() != null && !handle.getQualifiedName().equals(handle.getName())) {
				displayName = handle.getQualifiedName();
			} else {
				// displayName = handle.getDisplayLabel(
				// DesignElementHandle.USER_LABEL );
				displayName = handle.getName();
			}
			if (!StringUtil.isBlank(displayName)) {
				if (includeElementName) {
					return elementName + " - " + displayName; //$NON-NLS-1$
				}
				return displayName;
			}
			return elementName;
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Gets the master page count.
	 *
	 * @return the count of master page
	 */
	public static int getMasterPageAccount() {
		SlotHandle slotHandle = SessionHandleAdapter.getInstance().getReportDesignHandle().getMasterPages();

		Iterator<?> itor = slotHandle.iterator();

		int account = 0;

		while (itor.hasNext()) {
			account = account + 1;
			itor.next();
		}
		return account;
	}

	/**
	 * Gets the default content property name.
	 *
	 * @param parent
	 * @return Return the default content property name.
	 */
	// TODO this a temp resolve method.
	public static String getDefaultContentName(Object parent) {
		if (parent instanceof DesignElementHandle) {
			List<?> propDefns = ((DesignElementHandle) parent).getDefn().getContents();
			if (!propDefns.isEmpty()) {
				return ((IPropertyDefn) propDefns.get(0)).getName();
			}
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Get default slot id of give container element
	 *
	 * @param parent
	 * @return slot id, -1 if not found
	 */
	public static int getDefaultSlotID(Object parent) {
		int slotID = -1;
		if (parent instanceof GraphicMasterPageHandle) {
			slotID = IGraphicMaterPageModel.CONTENT_SLOT;
		} else if (parent instanceof ParameterGroupHandle) {
			slotID = IParameterGroupModel.PARAMETERS_SLOT;
		} else if (parent instanceof ReportDesignHandle) {
			slotID = IInternalReportDesignModel.BODY_SLOT;
		} else if (parent instanceof LibraryHandle) {
			slotID = IModuleModel.COMPONENT_SLOT;
		} else if (parent instanceof CellHandle) {
			slotID = ICellModel.CONTENT_SLOT;
		} else if (parent instanceof RowHandle) {
			slotID = ITableRowModel.CONTENT_SLOT;
		} else if (parent instanceof GridHandle) {
			slotID = IGridItemModel.ROW_SLOT;
		} else if (parent instanceof ThemeHandle) {
			slotID = IAbstractThemeModel.STYLES_SLOT;
		} else if (parent instanceof ReportItemThemeHandle) {
			slotID = IAbstractThemeModel.STYLES_SLOT;
		}
		return slotID;
	}

	/**
	 * Get the slot id of child
	 *
	 * @param parent
	 * @param child
	 * @return slot ID
	 */

	public static int findSlotID(Object parent, Object child) {
		assert parent instanceof DesignElementHandle;
		assert child instanceof DesignElementHandle;

		int slotID = ((DesignElementHandle) parent).findContentSlot((DesignElementHandle) child);

		return slotID;
	}

	/**
	 * Get the slot id of child If the slot id was not found, returns the default
	 * slot id
	 *
	 * @param parent
	 * @param child
	 * @return slot id
	 */
	public static int getSlotID(Object parent, Object child) {
		assert parent instanceof DesignElementHandle;

		int slotID = -1;

		if (child != null) {
			slotID = findSlotID(parent, child);
		} else {
			slotID = getDefaultSlotID(parent);
		}

		return slotID;
	}

	/**
	 * Get the slot id of child If the slot id was not found, returns the default
	 * slot id
	 *
	 * @param parent
	 * @param child
	 * @return slot id
	 */
	public static String getContentProperty(Object parent, Object child) {
		assert parent instanceof DesignElementHandle;

		String retValue = ""; //$NON-NLS-1$

		if (child != null) {
			retValue = ((DesignElementHandle) child).getContainerPropertyHandle().getDefn().getName();
		} else {
			retValue = getDefaultContentName(parent);
		}

		return retValue;
	}

	/**
	 * Find the position of the element. If the element is null, the position is
	 * last
	 *
	 * @param parent
	 * @param element
	 * @return position
	 */
	public static int findInsertPosition(DesignElementHandle parent, DesignElementHandle element) {
		// if after is null, insert at last
		if (element == null) {
			SlotHandle slotHandle = parent.getSlot(DEUtil.getDefaultSlotID(parent));
			if (slotHandle != null) {
				return slotHandle.getCount();
			}
			return -1;
		}
		return DEUtil.findPos(parent, element.getContainerSlotHandle().getSlotID(), element);
	}

	/**
	 * Map GUI defined property key to DE defined property key
	 *
	 * @param key
	 * @return DE defined property key
	 */
	public static String getGUIPropertyKey(String key) {
		if (key != null) {
			return propertiesMap.get(key);
		}
		return null;
	}

	/**
	 * Transform other units to pixel.
	 *
	 * @param handle DimensionHandle of model to keep the measure and units.
	 * @return The pixel value.
	 */
	public static double convertoToPixel(Object handle) {
		return convertToPixel(handle, 0, null);
	}

	/**
	 * Transform other units to pixel.
	 *
	 * @param object   model to keep the measure and units.
	 * @param fontSize the parent font size
	 * @return The pixel value.
	 */
	public static double convertToPixel(Object object, int fontSize) {
		return convertToPixel(object, fontSize, null);
	}

	/**
	 * Transform other units to pixel.
	 *
	 * @param object   model to keep the measure and units.
	 * @param refValue reference value of relative converting (default: the parent
	 *                 font size)
	 * @param refUnit  reference unit of relative converting (default: font unit
	 *                 "pt")
	 * @return The pixel value.
	 */
	public static double convertToPixel(Object object, int refValue, String refUnit) {

		double px = 0;
		double measure = 0;
		double calcValue = 0;
		String units = ""; //$NON-NLS-1$

		if (object instanceof DimensionValue) {
			DimensionValue dimension = (DimensionValue) object;
			measure = dimension.getMeasure();
			units = dimension.getUnits();
		} else if (object instanceof DimensionHandle) {
			DimensionHandle dimension = (DimensionHandle) object;
			measure = dimension.getMeasure();
			units = dimension.getUnits();
		}

		if (DesignChoiceConstants.UNITS_PX.equals(units)) {
			return measure;
		}

		// Default value is DesignChoiceConstants.UNITS_IN
		if ("".equalsIgnoreCase(units)) //$NON-NLS-1$
		{
			px = measure;
		}

		if (refValue == 0) {
			Font defaultFont = JFaceResources.getDefaultFont();
			FontData[] fontData = defaultFont.getFontData();
			refValue = fontData[0].getHeight();
		}

		if (DesignChoiceConstants.UNITS_EM.equals(units)) {
			px = DimensionUtil
					.convertTo(measure * refValue, DesignChoiceConstants.UNITS_PT,
							DesignChoiceConstants.UNITS_IN)
					.getMeasure();
		} else if (DesignChoiceConstants.UNITS_EX.equals(units)) {
			px = DimensionUtil
					.convertTo(measure * refValue / 3, DesignChoiceConstants.UNITS_PT,
							DesignChoiceConstants.UNITS_IN)
					.getMeasure();
		} else if (DesignChoiceConstants.UNITS_PERCENTAGE.equals(units)) {
			calcValue = (measure * refValue / 100);
			if (DesignChoiceConstants.UNITS_PX.equals(refUnit)) {
				return calcValue;
			}
			px = DimensionUtil
					.convertTo(calcValue, DesignChoiceConstants.UNITS_PT,
							DesignChoiceConstants.UNITS_IN)
					.getMeasure();
		}
		// added by gao if unit is "", set the unit is Design default unit
		else if ("".equals(units))//$NON-NLS-1$
		{
			units = SessionHandleAdapter.getInstance().getReportDesignHandle().getDefaultUnits();
			px = DimensionUtil.convertTo(measure, units, DesignChoiceConstants.UNITS_IN).getMeasure();
		} else if (units == null) {
			px = 0.0;
		} else {
			px = DimensionUtil.convertTo(measure, units, DesignChoiceConstants.UNITS_IN).getMeasure();
		}

		return MetricUtility.inchToPixel(px);
	}

	/**
	 * Transform other units to target unit.
	 *
	 * @param handle     dimension handle
	 * @param targetUnit target unit
	 * @return Return the converted value to double
	 */
	public static double convertToValue(DimensionHandle handle, String targetUnit) {
		double retValue = 0.0;

		if (handle.isSet()) {
			retValue = DimensionUtil.convertTo(handle.getMeasure(), handle.getUnits(), targetUnit).getMeasure();
		}
		return retValue;
	}

	/**
	 * Checks if the value can be converted to a valid Integer.
	 *
	 * @param val
	 * @return true if the value can be converted to a valid Integer, else false.
	 */
	public static boolean isValidInteger(String val) {
		try {
			Integer.parseInt(val);
		} catch (Exception e) {
			return false;
		}

		return true;
	}

	/**
	 * Checks if the value is a valid number, including any integer and float,
	 * double.
	 *
	 * @param val
	 * @return Return the check result of valid number
	 */
	public static boolean isValidNumber(String val) {
		try {
			Double.parseDouble(val);
		} catch (Exception e) {
			return false;
		}

		return true;
	}

	/**
	 * Try to split the given value to String[2]. The result format is as follows:
	 * [number][other]. If either part can not be determined, it will leave null.
	 *
	 * @param value given string value
	 * @return [number][other]
	 */
	public static String[] splitString(String value) {
		String[] spt = new String[2];

		if (value != null) {
			for (int i = value.length(); i > 0; i--) {
				if (isValidNumber(value.substring(0, i))) {
					spt[0] = value.substring(0, i);
					spt[1] = value.substring(i);

					break;
				}
			}

			if (spt[0] == null && spt[1] == null) {
				spt[1] = value;
			}
		}

		return spt;
	}

	/**
	 * If given value if null, return an empty string, or return itself.
	 *
	 * @param value a String value.
	 * @return non-null value.
	 */
	public static String resolveNull(String value) {
		return value == null ? "" : value; //$NON-NLS-1$
	}

	/**
	 * Converts the RGB object value to a String, the String format is "r,g,b", no
	 * quotation marks.
	 *
	 * @param rgb RGB value.
	 * @return String value.
	 */
	public static String getRGBText(RGB rgb) {
		if (rgb != null) {
			return rgb.red + "," + rgb.green + "," + rgb.blue; //$NON-NLS-1$ //$NON-NLS-2$
		}

		return ""; //$NON-NLS-1$
	}

	/**
	 * Converts the String value to an RGB object value, the String format is
	 * "r,g,b", no quotation marks.
	 *
	 * @param val String value.
	 * @return RGB value.
	 */
	public static RGB getRGBValue(String val) {
		if (val != null) {
			if (val.startsWith("#")) //$NON-NLS-1$
			{
				int rgb = ColorUtil.parseColor(val);

				if (rgb != -1) {
					return getRGBValue(rgb);
				}
			} else {
				String[] ss = val.split(","); //$NON-NLS-1$
				if (ss.length == 3) {
					try {
						int r = Integer.parseInt(ss[0]);
						int g = Integer.parseInt(ss[1]);
						int b = Integer.parseInt(ss[2]);

						return new RGB(r, g, b);
					} catch (NumberFormatException e) {
						return null;
					}
				}
			}
		}

		return null;
	}

	/**
	 * Converts an Integer value to an RGB object value, the Integer format is
	 * xRRGGBB.
	 *
	 * @param rgbValue Integer value.
	 * @return RGB value.
	 */
	public static RGB getRGBValue(int rgbValue) {
		if (rgbValue == -1) {
			return null;
		}

		return new RGB((rgbValue >> 16) & 0xff, (rgbValue >> 8) & 0xff, rgbValue & 0xff);
	}

	/**
	 * Converts an RGB object value to an Integer value, the Integer format is
	 * xRRGGBB.
	 *
	 * @param rgb RGB value.
	 * @return Integer value.
	 */
	public static int getRGBInt(RGB rgb) {
		if (rgb == null) {
			return -1;
		}

		return ((rgb.red & 0xff) << 16) | ((rgb.green & 0xff) << 8) | (rgb.blue & 0xff);
	}

	/**
	 * Gets the list of data sets which can be used for the specified element
	 *
	 * @param handle the handle of the element
	 * @return Returns the list of data sets which can be used for this element
	 */
	public static List<DataSetHandle> getDataSetList(DesignElementHandle handle) {
		List<DataSetHandle> dataSetList = new ArrayList<DataSetHandle>();
		if (handle instanceof ReportElementHandle) {
			if (handle instanceof ReportItemHandle) {
				DataSetHandle dataSet = ((ReportItemHandle) handle).getDataSet();
				if (dataSet != null && !dataSetList.contains(dataSet)) {
					dataSetList.add(dataSet);
				}
			}
			for (Iterator<DataSetHandle> itor = getDataSetList(handle.getContainer()).iterator(); itor.hasNext();) {
				DataSetHandle dataSet = itor.next();
				if (!dataSetList.contains(dataSet)) {
					dataSetList.add(dataSet);
				}
			}
		}
		return dataSetList;
	}

	/**
	 * Gets the list of data sets which can be used for the specified element
	 *
	 * @param handle the handle of the element
	 * @return Returns the list of data sets which can be used for this element
	 *         excluding itself
	 */
	public static List<DesignElementHandle> getDataSetListExcludeSelf(DesignElementHandle handle) {
		List<DesignElementHandle> dataSetList = new ArrayList<DesignElementHandle>();
		if (handle instanceof ReportElementHandle) {
			for (Iterator<DataSetHandle> itor = getDataSetList(handle.getContainer()).iterator(); itor.hasNext();) {
				DesignElementHandle dataSet = itor.next();
				if (!dataSetList.contains(dataSet)) {
					dataSetList.add(dataSet);
				}
			}
		}
		return dataSetList;
	}

	/**
	 * Get definition of model property.
	 *
	 * @param elementName
	 * @param propertyName
	 * @return Return the definition of model property.
	 */
	public static IElementPropertyDefn getPropertyDefn(String elementName, String propertyName) {
		IElementDefn elementDefn = getMetaDataDictionary().getElement(elementName);
		if (elementDefn != null) {
			return elementDefn.getProperty(propertyName);
		}
		return null;
	}

	/**
	 * Gets the proper expression for the given model
	 *
	 * @param model the given model
	 * @return Returns the proper expression for the given model, or null if no
	 *         proper one exists
	 */
	public static String getExpression(Object model) {
		if (model instanceof ParameterHandle) {
			// return IReportElementConstants.PARAMETER_PREFIX
			// + "[\"" + escape( ( (ParameterHandle) model ).getQualifiedName( )
			// ) + "\"]"; //$NON-NLS-1$ //$NON-NLS-2$
			return ExpressionUtil.createJSParameterValueExpression(((ParameterHandle) model).getQualifiedName());
		}
		// add for the cross tab
		if (model instanceof LevelHandle) {
			LevelHandle handle = (LevelHandle) model;
			DesignElementHandle temp = handle.getContainer();
			String dimensionName = ""; //$NON-NLS-1$
			while (temp != null) {
				if (temp instanceof org.eclipse.birt.report.model.api.olap.DimensionHandle) {
					dimensionName = ((org.eclipse.birt.report.model.api.olap.DimensionHandle) temp).getName();
					break;
				}
				temp = temp.getContainer();
			}
			return ExpressionUtil.createJSDimensionExpression(dimensionName, handle.getName());
		}
		if (model instanceof MeasureHandle) {
			return ExpressionUtil.createJSMeasureExpression((((MeasureHandle) model)).getName());
		}

		if (model instanceof DataSetItemModel) {
			String colName = ((DataSetItemModel) model).getAlias();

			if (colName == null || colName.trim().length() == 0) {
				colName = ((DataSetItemModel) model).getName();
			}
			return getColumnExpression(colName);
		}
		if (model instanceof ComputedColumnHandle) {
			if (isBindingCube(((ComputedColumnHandle) model).getElementHandle())) {
				return getDataExpression(((ComputedColumnHandle) model).getName());
			}
			return getColumnExpression(((ComputedColumnHandle) model).getName());
		}
		if (model instanceof ResultSetColumnHandle) {
			return getResultSetColumnExpression(((ResultSetColumnHandle) model).getColumnName());
		}
		if (model instanceof DataSetParameterHandle) {
			return IReportElementConstants.STOREDPROCUDURE_OUTPUT_PREFIX + "[\"" //$NON-NLS-1$
					+ escape(((DataSetParameterHandle) model).getName()) + "\"]"; //$NON-NLS-1$
		}
		if (model instanceof LevelAttributeHandle) {
			LevelAttributeHandle levelAttri = (LevelAttributeHandle) model;
			String levelName = levelAttri.getElement().getName();
			DesignElementHandle temp = levelAttri.getElementHandle().getContainer();
			String dimensionName = ""; //$NON-NLS-1$
			while (temp != null) {
				if (temp instanceof org.eclipse.birt.report.model.api.olap.DimensionHandle) {
					dimensionName = ((org.eclipse.birt.report.model.api.olap.DimensionHandle) temp).getName();
					break;
				}
				temp = temp.getContainer();
			}
			return ExpressionUtil.createJSDimensionExpression(dimensionName, levelName, levelAttri.getName());
		}
		if (model instanceof VariableElementHandle) {
			VariableElementHandle variable = (VariableElementHandle) model;

			return "vars[\"" + variable.getName() + "\"]";
		}
		return null;
	}

	/**
	 * Get the integer font size for string value.
	 *
	 * @param fontSize font size
	 * @return Returns the integer font size for string value.
	 */
	public static int getFontSize(String fontSize) {
		if (DesignChoiceConstants.FONT_SIZE_LARGER.equals(fontSize)) {
			fontSize = DesignChoiceConstants.FONT_SIZE_LARGE;
		} else if (DesignChoiceConstants.FONT_SIZE_SMALLER.equals(fontSize)) {
			fontSize = DesignChoiceConstants.FONT_SIZE_SMALL;
		} else if (fontSize == null) {
			fontSize = DesignChoiceConstants.FONT_SIZE_MEDIUM;
		}

		String rt = (String) DesignerConstants.fontMap.get(fontSize);

		if (rt != null) {
			return Integer.parseInt(rt);
		}

		String[] sp = DEUtil.splitString(fontSize);

		if (sp[0] != null && DEUtil.isValidNumber(sp[0])) {
			return (int) CSSUtil.convertToPoint(new DimensionValue(Double.parseDouble(sp[0]), sp[1]));
		}

		return 10;// as medium size.
	}

	/**
	 * Get the handle's font size 's string value. if the font size is relative,
	 * calculate the actual size according to its parent.
	 *
	 * @param handle The style handle to work with the style properties of this
	 *               element.
	 * @return The font size string value.
	 */
	public static String getFontSize(DesignElementHandle handle) {
		if (!(handle instanceof ReportItemHandle)) {
			if (handle instanceof ModuleHandle) {
				return DesignChoiceConstants.FONT_SIZE_MEDIUM;
			}
			if (handle instanceof GroupHandle) {
				handle = handle.getContainer();
			}
		}

		Object fontSizeValue = getModelFontSize(handle);

		if (fontSizeValue instanceof DimensionValue) {
			return ((DimensionValue) fontSizeValue).toString();
		} else if (fontSizeValue instanceof String) {
			String fontSize = (String) fontSizeValue;
			if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_LARGER)) {
				return getLargerFontSize(handle.getContainer());
			} else if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_SMALLER)) {
				return getSmallerFontSize(handle.getContainer());
			} else {
				return fontSize;
			}
		} else {
			return DesignChoiceConstants.FONT_SIZE_MEDIUM;
		}
	}

	private static String getLargerFontSize(DesignElementHandle handle) {
		if (!(handle instanceof ReportItemHandle)) {
			if (handle instanceof ModuleHandle) {
				for (int i = 0; i < DesignerConstants.fontSizes.length - 1; i++) {
					if (DesignChoiceConstants.FONT_SIZE_MEDIUM.equals(DesignerConstants.fontSizes[i][0])) {
						return DesignerConstants.fontSizes[i + 1][0];
					}
				}
			}
			if (handle instanceof GroupHandle) {
				handle = handle.getContainer();
			}
		}

		Object fontSizeValue = getModelFontSize(handle);

		if (fontSizeValue instanceof DimensionValue) {
			int parentSize = getFontSizeIntValue(handle.getContainer());
			int size = (int) CSSUtil.convertToPoint(fontSizeValue, parentSize) + 1;

			DimensionValue dm = new DimensionValue(size, "pt"); //$NON-NLS-1$
			return dm.toString();
		} else if (fontSizeValue instanceof String) {
			String fontSize = (String) fontSizeValue;
			if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_LARGER)) {
				return getLargerFontSize(handle.getContainer());
			} else if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_SMALLER)) {
				return getSmallerFontSize(handle.getContainer());
			} else {
				for (int i = 0; i < DesignerConstants.fontSizes.length - 1; i++) {
					if (fontSize.equals(DesignerConstants.fontSizes[i][0])) {
						return DesignerConstants.fontSizes[i + 1][0];
					}
				}
				return DesignerConstants.fontSizes[DesignerConstants.fontSizes.length - 1][0];
			}
		} else {
			return DesignChoiceConstants.FONT_SIZE_MEDIUM;
		}

	}

	private static String getSmallerFontSize(DesignElementHandle handle) {
		if (!(handle instanceof ReportItemHandle)) {
			if (handle instanceof ModuleHandle) {
				for (int i = DesignerConstants.fontSizes.length - 1; i > 0; i--) {
					if (DesignChoiceConstants.FONT_SIZE_MEDIUM.equals(DesignerConstants.fontSizes[i][0])) {
						return DesignerConstants.fontSizes[i - 1][0];
					}
				}
			}
			if (handle instanceof GroupHandle) {
				handle = handle.getContainer();
			}
		}

		Object fontSizeValue = getModelFontSize(handle);

		if (fontSizeValue instanceof DimensionValue) {
			int parentSize = getFontSizeIntValue(handle.getContainer());
			int size = (int) CSSUtil.convertToPoint(fontSizeValue, parentSize) - 1;

			size = (size < 1) ? 1 : size;

			DimensionValue dm = new DimensionValue(size, "pt"); //$NON-NLS-1$
			return dm.toString();
		} else if (fontSizeValue instanceof String) {
			String fontSize = (String) fontSizeValue;
			if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_LARGER)) {
				return getLargerFontSize(handle.getContainer());
			} else if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_SMALLER)) {
				return getSmallerFontSize(handle.getContainer());
			} else {
				for (int i = DesignerConstants.fontSizes.length - 1; i > 0; i--) {
					if (fontSize.equals(DesignerConstants.fontSizes[i][0])) {
						return DesignerConstants.fontSizes[i - 1][0];
					}
				}
				return DesignerConstants.fontSizes[0][0];
			}
		} else {
			return DesignChoiceConstants.FONT_SIZE_MEDIUM;
		}

	}

	/**
	 * Get the handle's font size int value. if the font size is relative, calculate
	 * the actual size according to its parent.
	 *
	 * @param handle The style handle to work with the style properties of this
	 *               element.
	 * @return The font size int value
	 */
	public static int getFontSizeIntValue(DesignElementHandle handle) {
		if (!(handle instanceof ReportItemHandle)) {
			if (handle instanceof ModuleHandle) {
				// return 10.
				String size = (String) DesignerConstants.fontMap.get(DesignChoiceConstants.FONT_SIZE_MEDIUM);
				return Integer.parseInt(size);
			}
			if (handle instanceof GroupHandle) {
				handle = handle.getContainer();
			}
		}

		if (handle.getPrivateStyle() != null && handle.getPrivateStyle().getFontSize().getAbsoluteValue() != null) {
			return (int) CSSUtil.convertToPoint(handle.getPrivateStyle().getFontSize().getAbsoluteValue(),
					getDefaultFontSize());
		}
		return getDefaultFontSize();
	}

	private static int getDefaultFontSize() {
		if (defaultFontSite == -1) {
			String size = (String) DesignerConstants.fontMap.get(DesignChoiceConstants.FONT_SIZE_MEDIUM);
			defaultFontSite = Integer.parseInt(size);
		}
		return defaultFontSite;
	}

	private static int getLargerFontSizeIntValue(DesignElementHandle handle) {
		if (!(handle instanceof ReportItemHandle)) {
			if (handle instanceof ModuleHandle) {
				// return 10.
				String size = (String) DesignerConstants.fontMap.get(DesignChoiceConstants.FONT_SIZE_MEDIUM);
				return Integer.parseInt(size) + 1;
			}
			if (handle instanceof GroupHandle) {
				handle = handle.getContainer();
			}
		}

		Object fontSizeValue = getModelFontSize(handle);

		if (fontSizeValue instanceof DimensionValue) {
			int size = getFontSizeIntValue(handle.getContainer());
			return (int) CSSUtil.convertToPoint(fontSizeValue, size) + 1;
		} else if (fontSizeValue instanceof String) {
			String fontSize = (String) fontSizeValue;
			if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_LARGER)) {
				return getLargerFontSizeIntValue(handle.getContainer());
			} else if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_SMALLER)) {
				return getSmallerFontSizeIntValue(handle.getContainer());
			} else {
				for (int i = 0; i < DesignerConstants.fontSizes.length - 1; i++) {
					if (fontSize.equals(DesignerConstants.fontSizes[i][0])) {
						return Integer.parseInt(DesignerConstants.fontSizes[i + 1][1]);
					}
				}
				return Integer.parseInt(DesignerConstants.fontSizes[DesignerConstants.fontSizes.length - 1][1]);
			}
		} else {
			// return 10 + 1.
			String size = (String) DesignerConstants.fontMap.get(DesignChoiceConstants.FONT_SIZE_MEDIUM);
			return Integer.parseInt(size) + 1;
		}
	}

	private static int getSmallerFontSizeIntValue(DesignElementHandle handle) {
		if (!(handle instanceof ReportItemHandle)) {
			if (handle instanceof ModuleHandle) {
				// return 10.
				String size = (String) DesignerConstants.fontMap.get(DesignChoiceConstants.FONT_SIZE_MEDIUM);
				return Integer.parseInt(size) - 1;
			}
			if (handle instanceof GroupHandle) {
				handle = handle.getContainer();
			}
		}

		Object fontSizeValue = getModelFontSize(handle);

		if (fontSizeValue instanceof DimensionValue) {
			int gParentFontSize = getFontSizeIntValue(handle.getContainer());
			int size = (int) CSSUtil.convertToPoint(fontSizeValue, gParentFontSize) - 1;
			if (size < 1) {
				return 1;
			}
			return size;

		} else if (fontSizeValue instanceof String) {
			String fontSize = (String) fontSizeValue;
			if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_LARGER)) {
				return getLargerFontSizeIntValue(handle.getContainer());
			} else if (fontSize.equals(DesignChoiceConstants.FONT_SIZE_SMALLER)) {
				return getSmallerFontSizeIntValue(handle.getContainer());
			} else {
				for (int i = DesignerConstants.fontSizes.length - 1; i > 0; i--) {
					if (fontSize.equals(DesignerConstants.fontSizes[i][0])) {
						return Integer.parseInt(DesignerConstants.fontSizes[i - 1][1]);
					}
				}
				return Integer.parseInt(DesignerConstants.fontSizes[0][1]);
			}
		} else {
			// return 10 -1.
			String size = (String) DesignerConstants.fontMap.get(DesignChoiceConstants.FONT_SIZE_MEDIUM);
			return Integer.parseInt(size) - 1;
		}
	}

	/**
	 * Since "&" in menu text has special meaning, we must escape it before
	 * displaying.
	 *
	 * @param src Source text.
	 * @return Escaped text.
	 */
	public static String getEscapedMenuItemText(String src) {
		if (src != null && src.indexOf('&') != -1) {
			src = src.replaceAll("\\&", "&&"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		return src;
	}

	/**
	 * Returns all font names for current system, the name list is sorted in
	 * alphabetical order.
	 *
	 * NOTES: Java 1.4 only support true type fonts.
	 *
	 * @return font names.
	 */
	public static String[] getSystemFontNames() {
		if (sorted_system_fonts == null) {
			sorted_system_fonts = getSystemFontNames(new AlphabeticallyComparator());
		}

		return sorted_system_fonts;
	}

	/**
	 * Returns all font names for current system. NOTES: Java 1.4 only support true
	 * type fonts.
	 *
	 * @param comparator Sort comparator.
	 * @return font names.
	 */
	synchronized public static String[] getSystemFontNames(AlphabeticallyComparator comparator) {
		if (scalable_system_fonts == null) {
			FontData[] fontDatas = Display.getCurrent().getFontList(null, true);

			scalable_system_fonts = new ArrayList<>();

			for (FontData fd : fontDatas) {
				scalable_system_fonts.add(fd.getName());
			}
		}

		if (non_scalable_system_fonts == null) {
			FontData[] fontDatas = Display.getCurrent().getFontList(null, false);

			non_scalable_system_fonts = new ArrayList<>();

			for (FontData fd : fontDatas) {
				non_scalable_system_fonts.add(fd.getName());
			}
		}

		SortedSet<String> set = new TreeSet<String>(comparator);

		for (String fontName : scalable_system_fonts) {
			set.add(fontName);
		}

		for (String fontName : non_scalable_system_fonts) {
			set.add(fontName);
		}

		return set.toArray(new String[set.size()]);
	}

	/**
	 * Gets the tool used to process multil-selection.
	 *
	 * @param modelList DE model list.
	 * @return The tool used to process multil-selection.
	 */
	public static GroupElementHandle getMultiSelectionHandle(List<?> modelList) {
		ModuleHandle designHandle = SessionHandleAdapter.getInstance().getReportDesignHandle();
		GroupElementHandle handle = GroupElementFactory.newGroupElement(designHandle, modelList);
		return handle;
	}

	/**
	 * Escapes \ and " following standard of Javascript
	 *
	 * @param str
	 * @return new string after escape special character
	 */
	public static String escape(String str) {
		String[][] chars = { { "\\\\", "\"", "\'", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
				}, { "\\\\\\\\", "\\\\\"", "\\\\\'", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
				} };
		String result = str;
		for (int i = 0; i < chars[0].length; i++) {
			result = result.replaceAll(chars[0][i], chars[1][i]);
		}
		return result;
	}

	/**
	 * Gets decimal string given the number of zeros.
	 *
	 * @param decPlaces number of decimal places
	 * @return Return the decimal string given the number of zeros.
	 */
	public static String getDecmalStr(int decPlaces) {

		String defaultDecs = "0000000000"; //$NON-NLS-1$
		String decStr = ""; //$NON-NLS-1$
		if (decPlaces > 0 && decPlaces < 10) {
			decStr = defaultDecs.substring(0, decPlaces);
		} else if (decPlaces >= 10) {
			if (decPlaces > 100) {
				decPlaces = 100;
			}
			int quotient = decPlaces / 10;
			int remainder = decPlaces % 10;

			StringBuilder s = new StringBuilder(100);
			for (int i = 0; i < quotient; i++) {
				s.append(defaultDecs);
			}
			s.append(defaultDecs.substring(0, remainder));

			decStr = s.toString();
		}
		return decStr;
	}

	/**
	 * @param transferSource
	 * @return true if parameter is parameter group.
	 */
	public static boolean isParameterGroup(Object transferSource) {
		// CascadingParameterGroup is extended from ParameterGroup, so it also
		// is ParameterGroup
		return (transferSource instanceof IDesignElement && (((IDesignElement) transferSource).getDefn().getName()
				.equals(ReportDesignConstants.PARAMETER_GROUP_ELEMENT)
				|| ((IDesignElement) transferSource).getDefn().getName()
						.equals(ReportDesignConstants.CASCADING_PARAMETER_GROUP_ELEMENT)));
	}

	/**
	 * Get styles
	 *
	 * @return Alphabetically sorted styles list.
	 */
	public static Iterator<?> getStyles() {
		return getStyles(true, new AlphabeticallyComparator());
	}

	/**
	 * Get styles
	 *
	 * @param showCurrent show the current style
	 * @return Alphabetically sorted styles list.
	 */
	public static Iterator<?> getStyles(boolean showCurrent) {
		return getStyles(showCurrent, new AlphabeticallyComparator());
	}

	/**
	 * Get styles
	 *
	 * @param showCurrent show current style
	 * @param comparator  comparator
	 * @return return styles list sorted with given comparator.
	 */
	public static Iterator<Object> getStyles(boolean showCurrent, Comparator<Object> comparator) {
		List<Object> styles = null;
		ModuleHandle module = SessionHandleAdapter.getInstance().getReportDesignHandle();

		if (module instanceof ReportDesignHandle) {
			styles = module.getAllStyles();
		} else if (module instanceof LibraryHandle) {
			styles = new ArrayList<Object>();
			if (showCurrent) {
				ThemeHandle theme = ((LibraryHandle) module).getTheme();

				if (theme != null) {
					styles.addAll(theme.getAllStyles());
				}
			} else {
				SlotHandle themeSlot = ((LibraryHandle) module).getThemes();
				styles = new ArrayList<Object>();
				for (Iterator<?> iter = themeSlot.getContents().iterator(); iter.hasNext();) {
					Object obj = iter.next();
					if (obj instanceof AbstractThemeHandle) {
						AbstractThemeHandle theme = (AbstractThemeHandle) obj;
						for (int i = 0; i < theme.getAllCssStyleSheets().size(); i++) {
							styles.add(theme.getAllCssStyleSheets().get(i));
						}
						for (int i = 0; i < theme.getStyles().getCount(); i++) {
							styles.add(theme.getStyles().getContents().get(i));
						}
					}
				}
			}
		}

		if (styles == null || styles.isEmpty()) {
			return Collections.emptyList().iterator();
		}

		if (comparator == null) {
			return styles.iterator();
		}

		Object[] stylesArray = styles.toArray(new Object[styles.size()]);
		Arrays.sort(stylesArray, comparator);

		return Arrays.asList(stylesArray).iterator();
	}

	/**
	 * Get styles
	 *
	 * @param comparator comparator of the style
	 * @return Return the styles
	 */
	public static Iterator<?> getStyles(Comparator<Object> comparator) {
		return getStyles(true, comparator);
	}

	/**
	 * Get styles
	 *
	 * @return Alphabetically sorted styles list.
	 */
	public static Iterator<Object> getLocalStyles() {
		return getLocalStyles(new AlphabeticallyComparator());
	}

	/**
	 * Get styles
	 *
	 * @param comparator
	 * @return return styles list sorted with given comparator.
	 */
	public static Iterator<Object> getLocalStyles(Comparator<Object> comparator) {
		List<DesignElementHandle> styles = null;
		ModuleHandle module = SessionHandleAdapter.getInstance().getReportDesignHandle();

		if (module instanceof ReportDesignHandle) {
			styles = module.getStyles().getContents();
		} else if (module instanceof LibraryHandle) {
			styles = new ArrayList<DesignElementHandle>();
			ThemeHandle theme = ((LibraryHandle) module).getTheme();

			if (theme != null) {
				styles.addAll(theme.getAllStyles());
			}
		}

		Object[] stylesArray = (styles == null ? new Object[0] : styles.toArray());

		if (comparator != null) {
			Arrays.sort(stylesArray, comparator);
		}
		return Arrays.asList(stylesArray).iterator();
	}

	/**
	 * Get styles
	 *
	 * @param theme theme handle
	 *
	 * @return Alphabetically sorted styles list.
	 */
	public static Iterator<Object> getStyles(AbstractThemeHandle theme) {
		return getStyles(theme, new AlphabeticallyComparator());
	}

	/**
	 * Get styles
	 *
	 * @param theme      theme handle
	 * @param comparator comparator if the styles
	 * @return return styles list sorted with given comparator.
	 */
	public static Iterator<Object> getStyles(AbstractThemeHandle theme, Comparator<Object> comparator) {
		List<DesignElementHandle> styles = new ArrayList<DesignElementHandle>();

		if (theme != null) {
			styles.addAll(theme.getAllStyles());
		} else {
			ModuleHandle module = SessionHandleAdapter.getInstance().getReportDesignHandle();

			if (module instanceof LibraryHandle) {
				styles = new ArrayList<DesignElementHandle>();
				theme = ((LibraryHandle) module).getTheme();

				if (theme != null) {
					styles.addAll(theme.getAllStyles());
				}
			}
		}

		Object[] stylesArray = styles.toArray(new Object[styles.size()]);

		if (comparator != null) {
			Arrays.sort(stylesArray, comparator);
		}

		return Arrays.asList(stylesArray).iterator();
	}

	/**
	 * Checks if two strings have same value.
	 *
	 * @param str1 string 1 of compare
	 * @param str2 string 2 of compare
	 * @return Return the result of the string compare
	 */
	public static boolean isSameString(String str1, String str2) {
		if ((str1 == null && str2 == null) || (str1 != null && str1.equals(str2))) {
			return true;
		}
		return false;
	}

	/**
	 * Create a row expression base on a binding column name.
	 *
	 * @param columnName the column name
	 * @return the expression, or null if the column name is blank.
	 */
	public static String getColumnExpression(String columnName) {
		if (StringUtil.isBlank(columnName)) {
			return null;
		}
		return ExpressionUtil.createJSRowExpression(columnName);
	}

	/**
	 * Get the data expression
	 *
	 * @param columnName column name
	 * @return Return the data expression
	 */
	public static String getDataExpression(String columnName) {
		if (StringUtil.isBlank(columnName)) {
			return null;
		}
		return ExpressionUtil.createJSDataExpression(columnName);
	}

	/**
	 * Create a row expression base on a result set column name.
	 *
	 * @param columnName the column name
	 * @return the expression, or null if the column name is blank.
	 */
	public static String getResultSetColumnExpression(String columnName) {
		if (StringUtil.isBlank(columnName)) {
			return null;
		}
		return ExpressionUtil.createJSDataSetRowExpression(columnName);
	}

	/**
	 * Relativizes the path against this base path.
	 *
	 * @param basePath the base path
	 * @param path     the path to convert
	 * @return The relative path based on the base path if it is possible, or the
	 *         original path
	 *
	 */
	public static String getRelativedPath(String basePath, String path) {
		File baseFile = new File(basePath);
		if (baseFile.isFile()) {
			baseFile = baseFile.getParentFile();
		}
		return URIUtil.getRelativePath(baseFile.getAbsolutePath(), path);
	}

	/**
	 * Returns the handle of the action of the given element.
	 *
	 * @param element the element handle
	 * @return the handle of the action, or null if the element is not a proper type
	 */
	public static ActionHandle getActionHandle(ReportElementHandle element) {
		ActionHandle actionHandle = null;
		if (element instanceof LabelHandle) {
			actionHandle = ((LabelHandle) element).getActionHandle();
		} else if (element instanceof DataItemHandle) {
			actionHandle = ((DataItemHandle) element).getActionHandle();
		} else if (element instanceof ImageHandle) {
			actionHandle = ((ImageHandle) element).getActionHandle();
		} else if (element instanceof LevelHandle) {
			actionHandle = ((LevelHandle) element).getActionHandle();
		} else if (element instanceof MeasureHandle) {
			actionHandle = ((MeasureHandle) element).getActionHandle();
		}
		return actionHandle;
	}

	/**
	 * Sets the handle of the action of the given element.
	 *
	 * @param element the element handle to set
	 * @param action  the action
	 *
	 * @return the handle of the action, or null if the element is not a proper type
	 *
	 * @throws SemanticException
	 */
	public static ActionHandle setAction(ReportElementHandle element, Action action) throws SemanticException {
		ActionHandle actionHandle = null;
		if (element instanceof LabelHandle) {
			actionHandle = ((LabelHandle) element).setAction(action);
		} else if (element instanceof DataItemHandle) {
			actionHandle = ((DataItemHandle) element).setAction(action);
		} else if (element instanceof ImageHandle) {
			actionHandle = ((ImageHandle) element).setAction(action);
		} else if (element instanceof LevelHandle) {
			actionHandle = ((LevelHandle) element).setAction(action);
		} else if (element instanceof MeasureHandle) {
			actionHandle = ((MeasureHandle) element).setAction(action);
		}
		return actionHandle;
	}

	private static Object getModelFontSize(DesignElementHandle handle) {
		// Fix 118374
		// ReportTemplateElement is the only exception that is a DesignElemtn
		// but doesn't have Style attached.
		StyleHandle styleHandle = handle.getPrivateStyle();
		Object fontSizeValue = null;
		if (styleHandle != null) {
			fontSizeValue = handle.getPrivateStyle().getFontSize().getValue();
		}
		return fontSizeValue;
	}


	/**
	 * Get the report themes
	 *
	 * @return Return the report themes
	 */
	public static Iterator<Object> getThemes() {
		return getThemes(new AlphabeticallyComparator());
	}

	private static Iterator<Object> getThemes(AlphabeticallyComparator comparator) {
		List themes = SessionHandleAdapter.getInstance().getReportDesignHandle()
				.getVisibleThemes(IAccessControl.DIRECTLY_INCLUDED_LEVEL);

		Object[] themesArray = themes.toArray();

		if (comparator != null) {
			Arrays.sort(themesArray, comparator);
		}
		return Arrays.asList(themesArray).iterator();
	}

	/**
	 * Generates GroupElementHandle for given model list.
	 *
	 * @param modelList
	 * @return Return the group element handle
	 */
	public static GroupElementHandle getGroupElementHandle(List<?> modelList) {
		ModuleHandle handle = SessionHandleAdapter.getInstance().getReportDesignHandle();

		if (handle == null) {
			return GroupElementFactory.newGroupElement(handle, Collections.EMPTY_LIST);
		}
		return GroupElementFactory.newGroupElement(handle, modelList);

	}

	/**
	 * Checks if the library is included.
	 *
	 * @param handle
	 * @return Return the check of included library
	 */
	public static boolean isIncluded(LibraryHandle handle) {
		return handle.getNamespace() != null;
	}

	/**
	 * Get classes with default comparator
	 *
	 * @return List of classes
	 */
	public static List<IClassInfo> getClasses() {

		return getClasses(new AlphabeticallyComparator());
	}

	/**
	 * Get classes with specified comparator
	 *
	 * @param comp the comparator
	 * @return List of classes
	 */
	public static List<IClassInfo> getClasses(AlphabeticallyComparator comp) {
		List<IClassInfo> classes = getMetaDataDictionary().getClasses();
		Collections.sort(classes, comp);

		// Fix bug 187178: Remove Total JS object
		classes.remove(TOTAL_CLASS);
		return classes;
	}

	/**
	 * Get methods with default comparator, the return list doesn't include
	 * constructors
	 *
	 * @param classInfo
	 * @return List of methods
	 */
	public static List<IMethodInfo> getMethods(IClassInfo classInfo) {
		return getMethods(classInfo, false, new AlphabeticallyComparator());
	}

	/**
	 * Get methods with specified comparator, the list doesn't include constructors
	 *
	 * @param classInfo class info
	 * @param comp      The comparator
	 * @return List of methods
	 */
	public static List<IMethodInfo> getMethods(IClassInfo classInfo, AlphabeticallyComparator comp) {
		return getMethods(classInfo, false, comp);
	}

	/**
	 * Get methods with default comparator constructors
	 *
	 * @param classInfo          class info
	 * @param includeConstructor include constructor
	 * @return List of methods
	 */
	public static List<IMethodInfo> getMethods(IClassInfo classInfo, boolean includeConstructor) {
		return getMethods(classInfo, includeConstructor, new AlphabeticallyComparator());
	}

	/**
	 * Get methods with default comparator
	 *
	 * @param classInfo          class info
	 * @param includeConstructor include constructor
	 * @param comp               comparator
	 * @return List of methods
	 */
	public static List<IMethodInfo> getMethods(IClassInfo classInfo, boolean includeConstructor,
			AlphabeticallyComparator comp) {
		List<IMethodInfo> mds = new ArrayList<IMethodInfo>();

		if (includeConstructor) {
			IMethodInfo mi = classInfo.getConstructor();
			if (mi != null) {
				mds.add(mi);
			}
		}

		List<IMethodInfo> methods = classInfo.getMethods();
		Collections.sort(methods, comp);
		mds.addAll(methods);

		return mds;
	}

	/**
	 * Get members with default comparator
	 *
	 * @param classInfo class info
	 * @return List of members
	 */
	public static List<IMemberInfo> getMembers(IClassInfo classInfo) {
		return getMembers(classInfo, new AlphabeticallyComparator());
	}

	/**
	 * Get members with specified comparator
	 *
	 * @param classInfo class info
	 * @param comp      The comparator
	 * @return List of methods
	 */
	public static List<IMemberInfo> getMembers(IClassInfo classInfo, AlphabeticallyComparator comp) {
		List<IMemberInfo> members = classInfo.getMembers();
		Collections.sort(members, comp);

		return members;

	}

	/**
	 *
	 * Return DesignElementHandle available method's argument type name.
	 *
	 * @param handle     DesignElementHandle.
	 * @param methodName method name
	 * @param argIndex   starts from 0.
	 * @return Return the design element handle available method's argument type
	 *         name.
	 */
	public static String getMethodArgumentType(DesignElementHandle handle, String methodName, int argIndex) {
		if (handle instanceof DataSetHandle) {
			return ReportDesignConstants.DATA_SET_ELEMENT;
		}
		if (handle instanceof DataSourceHandle) {
			return ReportDesignConstants.DATA_SOURCE_ELEMENT;
		}

		List<IElementPropertyDefn> methods = handle.getDefn().getLocalMethods();
		for (Iterator<IElementPropertyDefn> iter = methods.iterator(); iter.hasNext();) {
			IMethodInfo method = ((ElementPropertyDefn) iter.next()).getMethodInfo();
			if (method.getName().equals(methodName)) {
				Iterator<IArgumentInfoList> argumentListIterator = method.argumentListIterator();
				if (argumentListIterator.hasNext()) {
					IArgumentInfoList argumentInfoList = argumentListIterator.next();
					int i = 0;
					for (Iterator<IArgumentInfo> iterator = argumentInfoList.argumentsIterator(); iterator
							.hasNext(); i++) {
						Object arg = iterator.next();
						if (argIndex == i) {
							return ((IArgumentInfo) arg).getType();
						}
					}

				}
				return null;
			}
		}
		return null;
	}

	/**
	 * Get a DesignElementHandle's method's all arguments.
	 *
	 * @param handle
	 * @param methodName
	 * @return Arguments list, each value is an IArgumentInfo object.
	 */
	public static List<IArgumentInfo> getDesignElementMethodArgumentsInfo(DesignElementHandle handle,
			String methodName) {
		List<IElementPropertyDefn> methods = handle.getDefn().getMethods();
		List<IArgumentInfo> args = new ArrayList<IArgumentInfo>();

		for (Iterator<IElementPropertyDefn> iter = methods.iterator(); iter.hasNext();) {
			IMethodInfo method = ((ElementPropertyDefn) iter.next()).getMethodInfo();
			if (method.getName().equals(methodName)) {
				Iterator<IArgumentInfoList> argumentListIterator = method.argumentListIterator();
				if (argumentListIterator.hasNext()) {
					IArgumentInfoList argumentInfoList = argumentListIterator.next();

					if (argumentInfoList != null) {
						for (Iterator<IArgumentInfo> iterator = argumentInfoList.argumentsIterator(); iterator
								.hasNext();) {
							IArgumentInfo arg = iterator.next();
							args.add(arg);
						}
					}
				}
			}
		}
		return args;
	}

	/**
	 * Get the data sources
	 *
	 * @return Return the data sources
	 * @deprecated
	 */
	@Deprecated
	public static List<?> getDataSources() {
		ModuleHandle moduleHandle = SessionHandleAdapter.getInstance().getReportDesignHandle();
		if (moduleHandle != null) {
			return moduleHandle.getVisibleDataSources();
		}
		return new ArrayList();
	}

	/**
	 * Returns all available column bindings for the given element
	 *
	 * @param handle the handle of the element
	 * @return the list of all column bindings available.The list order is from the
	 *         top to the given element
	 */
	public static List<?> getAllColumnBindingList(DesignElementHandle handle) {
		return getAllColumnBindingList(handle, true);
	}

	/**
	 * Returns all available column bindings for the given element.
	 *
	 * @param handle      the handle of the element
	 * @param includeSelf true if includes the element itself, or false only
	 *                    includes bindings in the containers
	 * @return the list of all column bindings available.The list order is from the
	 *         top to the given element
	 */

	public static List getAllColumnBindingList(DesignElementHandle handle, boolean includeSelf) {
		List bindingList = new ArrayList();
		if (handle instanceof ReportElementHandle || handle instanceof ContentElementHandle) {
			Iterator iterator = getBindingColumnIterator(handle);
			while (iterator.hasNext()) {
				bindingList.add(iterator.next());
			}
			bindingList.addAll(0, getAllColumnBindingList(handle.getContainer(), true));
		}
		return bindingList;
	}

	/**
	 * Returns all visible column bindings in the holder scope for the given element
	 *
	 * @param handle the handle of the element
	 * @return the list of all visible column bindings.The list order is from the
	 *         top to the given element
	 */
	public static List<ComputedColumnHandle> getVisiableColumnBindingsList(DesignElementHandle handle) {
		return getVisiableColumnBindingsList(handle, true);
	}

	/**
	 * Returns all visible column bindings for the given element
	 *
	 * @param handle      the handle of the element
	 * @param includeSelf include the column binding himself
	 * @return the list of all visible column bindings.The list order is from the
	 *         top to the given element
	 */
	public static List getVisiableColumnBindingsList(DesignElementHandle handle,
			boolean includeSelf) {
		List bindingList = new ArrayList();
		if (includeSelf) {
			Iterator iterator = getBindingColumnIterator(handle);
			while (iterator.hasNext()) {
				bindingList.add(iterator.next());
			}
		}
		ReportItemHandle holder = getBindingHolder(handle);
		if (holder != null) {
			for (DesignElementHandle elementHandle = handle.getContainer(); elementHandle != holder
					.getContainer(); elementHandle = elementHandle.getContainer()) {
				List subBindingList = new ArrayList();
				Iterator iterator = getBindingColumnIterator(elementHandle);
				while (iterator.hasNext()) {
					subBindingList.add(iterator.next());
				}
				bindingList.addAll(0, subBindingList);
			}
		}
		return bindingList;
	}

	/**
	 * Returns the element handle which can save binding columns the given element
	 *
	 * @param handle the handle of the element which needs binding columns
	 * @return the holder for the element,or itself if no holder available
	 */
	public static ReportItemHandle getBindingHolder(DesignElementHandle handle) {
		return getBindingHolder(handle, false);
	}

	/**
	 * Get binding holder
	 *
	 * @param handle   designe element handle
	 * @param skipSelf skip elemnt himself
	 * @return Return the binding holder
	 */
	public static ReportItemHandle getBindingHolder(DesignElementHandle handle, boolean skipSelf) {
		if (skipSelf || (handle instanceof ContentElementHandle)) {
			return getBindingHolder(handle.getContainer());
		}

		if (handle instanceof ReportElementHandle) {
			/*
			 * if ( handle instanceof ListingHandle ) { return (ReportItemHandle) handle; }
			 */
			if (handle instanceof ReportItemHandle) {
				if (((ReportItemHandle) handle).getDataBindingReference() != null
						|| ((ReportItemHandle) handle).getCube() != null
						|| ((ReportItemHandle) handle).getDataSet() != null
						|| ((ReportItemHandle) handle).columnBindingsIterator().hasNext()) {
					return (ReportItemHandle) handle;
				}
			}
			ReportItemHandle result = getBindingHolder(handle.getContainer());
			if (result == null && handle instanceof ReportItemHandle)
			// && !( handle instanceof GridHandle ) )
			{
				result = (ReportItemHandle) handle;
			}
			return result;
		}
		return null;
	}

	/**
	 * Get binding root
	 *
	 * @param handle
	 * @return Return the binding root
	 */
	public static ReportItemHandle getBindingRoot(DesignElementHandle handle) {
		return getBindingRoot(handle, false);
	}

	/**
	 * Get the binding root
	 *
	 * @param handle   design element handle
	 * @param skipSelf skip element himself
	 * @return Return the binding root
	 */
	public static ReportItemHandle getBindingRoot(DesignElementHandle handle, boolean skipSelf) {
		if (skipSelf || (handle instanceof ContentElementHandle)) {
			return getBindingRoot(handle.getContainer());
		}

		if (handle instanceof ReportElementHandle) {
			/*
			 * if ( handle instanceof ListingHandle ) { return (ReportItemHandle) handle; }
			 */
			if (handle instanceof ReportItemHandle) {
				if (((ReportItemHandle) handle).getDataBindingReference() != null
						|| ((ReportItemHandle) handle).getCube() != null
						|| ((ReportItemHandle) handle).getDataSet() != null) {
					return (ReportItemHandle) handle;
				}
			}
			ReportItemHandle result = getBindingRoot(handle.getContainer());
			return result;
		}
		return null;
	}

	/**
	 * Return the first DataSetHandle for a report item.
	 *
	 * If the report item has no DataSetHandle, search for it's container if
	 * container is not a ListingHandle.
	 *
	 * @param handle the ReportItemHandle
	 * @return Available DataSetHandle
	 */
	public static DataSetHandle getFirstDataSet(DesignElementHandle handle) {
		DataSetHandle dataSetHandle = null;
		if (handle instanceof ReportItemHandle) {
			dataSetHandle = ((ReportItemHandle) handle).getDataSet();
		}
		if (dataSetHandle == null) {
			for (DesignElementHandle elementHandle = handle; elementHandle != null; elementHandle = elementHandle
					.getContainer()) {
				if (elementHandle instanceof ListingHandle
						&& (dataSetHandle = ((ListingHandle) elementHandle).getDataSet()) != null) {
					return dataSetHandle;
				}
			}
		}
		return dataSetHandle;
	}

	/**
	 * Get the first data source
	 *
	 * @param handle design element handle
	 * @return Return the first data source
	 */
	public static Object getFirstDataSource(DesignElementHandle handle) {
		return getFirstDataSource(handle, true);
	}

	/**
	 * Get the first data source
	 *
	 * @param handle        design element handle
	 * @param findContainer find container
	 * @return Return the first data source
	 */
	public static Object getFirstDataSource(DesignElementHandle handle, boolean findContainer) {
		if (handle instanceof ReportItemHandle) {
			ReportItemHandle item = (ReportItemHandle) handle;
			if (item.getDataBindingReference() != null) {
				return getFirstDataSource(item.getDataBindingReference(), false);
			} else if (item.getCube() != null) {
				return item.getCube();
			} else if (item.getDataSet() != null) {
				return item.getDataSet();
			}
		}
		if (handle.getContainer() != null && findContainer) {
			return getFirstDataSource(handle.getContainer(), findContainer);
		}
		return null;
	}

	/**
	 * Get a container that is a ListingHandle that can hold dataset.
	 *
	 * @param container design element for the container
	 * @return Return the container that is a ListingHandle that can hold dataset.
	 */
	public static ListingHandle getListingContainer(DesignElementHandle container) {
		for (DesignElementHandle elementHandle = container; elementHandle != null; elementHandle = elementHandle
				.getContainer()) {
			if (elementHandle instanceof ListingHandle) {
				return (ListingHandle) elementHandle;
			}
		}
		return null;
	}

	/**
	 * Add a binding column on the given element
	 *
	 * @param handle  the handle of the elementIt should be a ReportItemHandle or a
	 *                GroupHandle
	 * @param column  the column to add
	 * @param inForce true to add the column with duplicated expression,or false not
	 *                to do
	 *
	 * @return the handle of the binding column,or null if failed
	 * @throws SemanticException
	 */
	public static ComputedColumnHandle addColumn(DesignElementHandle handle, ComputedColumn column, boolean inForce)
			throws SemanticException {
		assert handle instanceof ReportItemHandle;
		return ((ReportItemHandle) handle).addColumnBinding(column, inForce);
	}

	/**
	 * Returns the binding column iterator of the given element
	 *
	 * @param handle the handle of the element. It should be a ReportItemHandle or a
	 *               GroupHandle,or an empty iterator will be returned.
	 * @return the iterator of binding columns
	 */
	public static Iterator getBindingColumnIterator(DesignElementHandle handle) {
		if (handle instanceof ReportItemHandle) {
			return ((ReportItemHandle) handle).columnBindingsIterator();
		}
		return Collections.EMPTY_LIST.iterator();
	}

	/**
	 * Return the expression for the given binding column based on the given element
	 *
	 * @param baseElement the base element
	 * @param column      the binding column
	 * @return the expression for the column
	 */
	public static String getBindingexpression(DesignElementHandle baseElement, ComputedColumnHandle column) {
		return getBindingexpression(baseElement, column, true);
	}

	/**
	 * Get the binding expression
	 *
	 * @param baseElement   the base element
	 * @param column        the binding column
	 * @param checkOutLevel check out level
	 * @return Return the binding expression
	 */
	public static String getBindingexpression(DesignElementHandle baseElement, ComputedColumnHandle column,
			boolean checkOutLevel) {
		String exp = IReportElementConstants.BINDING_COLUMN_PREFIX;
		if (isBindingCube(column.getElementHandle())) {
			exp = ExpressionUtil.DATA_INDICATOR;
		}
		if (checkOutLevel) {
			for (int i = 0; i < getBindingLevel(column.getElementHandle(), baseElement); i++) {
				exp += IReportElementConstants.OUTER_BINDING_COLUMN_PREFIX;
			}
		}
		exp += "[\"" + DEUtil.escape(column.getName()) + "\"]"; //$NON-NLS-1$ //$NON-NLS-2$
		return exp;
	}

	/**
	 * Get the row number expression
	 *
	 * @param baseElement   the base element
	 * @param elementHandle element handle
	 * @return Return the row number expression
	 */
	public static String getRowNumExpression(DesignElementHandle baseElement, DesignElementHandle elementHandle) {
		return getRowNumExpression(baseElement, elementHandle, true);
	}

	/**
	 * Get the row number expression
	 *
	 * @param baseElement   the base element
	 * @param elementHandle element handle
	 * @param checkOutLevel check out level
	 * @return Return the row number expression
	 */
	public static String getRowNumExpression(DesignElementHandle baseElement, DesignElementHandle elementHandle,
			boolean checkOutLevel) {
		String exp = IReportElementConstants.BINDING_COLUMN_PREFIX;
		if (checkOutLevel) {
			for (int i = 0; i < getBindingLevel(elementHandle, baseElement); i++) {
				exp += IReportElementConstants.OUTER_BINDING_COLUMN_PREFIX;
			}
		}
		exp += ".__rownum"; // $NON-NLS-2$
		return exp;
	}

	/**
	 * Verify if a cube binding exists
	 *
	 * @param element
	 * @return Return the verification result
	 */
	public static boolean isBindingCube(DesignElementHandle element) {
		if (element == null) {
			return false;
		}
		if (element instanceof ReportItemHandle) {
			if (((ReportItemHandle) element).getCube() != null) {
				// check if this is a binding data model
				if (((ReportItemHandle) element).getDataSet() != null && (element instanceof TableHandle)) {
					return false;
				}
				return true;
			} else if (((ReportItemHandle) element)
					.getDataBindingType() == ReportItemHandleImpl.DATABINDING_TYPE_REPORT_ITEM_REF) {
				return isBindingCube(((ReportItemHandle) element).getDataBindingReference());
			} else if (((ReportItemHandle) element)
					.getDataBindingType() == ReportItemHandleImpl.DATABINDING_TYPE_DATA) {
				return false;
			}
		}
		if (element.getContainer() != null) {
			return isBindingCube(element.getContainer());
		}
		return false;
	}

	/**
	 * Returns the level between the holder and the given handle
	 *
	 * @param holder      the handle of the holder
	 * @param baseElement the handle of the base element
	 *
	 * @return the level between the holder and the base element, or -1 if the
	 *         element is not a children of the holder
	 */
	public static int getBindingLevel(DesignElementHandle holder, DesignElementHandle baseElement) {
		int level = 0;
		for (DesignElementHandle elementHandle = baseElement; elementHandle
				.getContainer() != null; elementHandle = getBindingHolder(elementHandle).getContainer(), level++) {
			DesignElementHandle bindingHolder = getBindingHolder(elementHandle);
			if ((bindingHolder == holder) || (holder instanceof GroupHandle && bindingHolder == holder.getContainer()) || (bindingHolder == null)) {
				return level;
			}
		}
		return -1;
	}

	/**
	 * Check if the given element is linked/extends from a library or not.
	 *
	 * @param handle the handle of the element to check
	 * @return true if it is linked from a library ,or false if else;
	 *
	 */
	public static boolean isLinkedElement(DesignElementHandle handle) {
		if (handle != null && handle.getExtends() != null) {
			return handle.getExtends().getRoot() instanceof LibraryHandle;
		}
		return false;
	}

	/**
	 * Return the group list of the given element.
	 *
	 * @param handle the handle of the element.
	 * @return the group list of the given element.
	 *
	 * @deprecated Use {@link UIUtil.getGroups()}
	 */
	@Deprecated
	public static List<DesignElementHandle> getGroups(DesignElementHandle handle) {
		List<DesignElementHandle> groupList = new ArrayList<DesignElementHandle>();
		if (handle instanceof ListingHandle) {
			SlotHandle groupSlotHandle = ((ListingHandle) handle).getGroups();
			for (Iterator<DesignElementHandle> iter = groupSlotHandle.iterator(); iter.hasNext();) {
				GroupHandle group = (GroupHandle) iter.next();
				groupList.add(group);
			}
			return groupList;
		}

		DesignElementHandle result = handle.getContainer();
		if (result != null) {
			if (result instanceof GroupHandle) {
				groupList.add(result);
				return groupList;
			}
			return getGroups(result);
		}

		return groupList;
	}

	/**
	 * The group container is ListingHandler, list, table, and so on.
	 */
	public static final String TYPE_GROUP_LISTING = "listing"; //$NON-NLS-1$

	/**
	 * The group container is GroupHandler
	 */
	public static final String TYPE_GROUP_GROUP = "group"; //$NON-NLS-1$

	/**
	 * other container, has none group.
	 */
	public static final String TYPE_GROUP_NONE = "none"; //$NON-NLS-1$

	/**
	 * Return the group container type of the given element handle.
	 *
	 * @param handle the handle of the element.
	 * @return the group container type of the given element.
	 */
	public static String getGroupControlType(DesignElementHandle handle) {
		if (handle instanceof ListingHandle) {
			return TYPE_GROUP_LISTING;
		}

		DesignElementHandle result = handle.getContainer();
		if (result != null) {
			if (result instanceof GroupHandle) {
				return TYPE_GROUP_GROUP;
			}
			return getGroupControlType(result);
		}
		return TYPE_GROUP_NONE;
	}

	/**
	 * Get the string enclosed with quote.
	 *
	 * @param string
	 * @return Return the string enclosed with quote.
	 */
	public static String addQuote(String string) {
		if (string != null && (!(string.startsWith("\"") && string.endsWith("\"")))) //$NON-NLS-1$//$NON-NLS-2$
		{
			return "\"" + string + "\""; //$NON-NLS-1$//$NON-NLS-2$
		}
		return string;
	}

	/**
	 * Remove the quote if the string enclosed width quote.
	 *
	 * @param string
	 * @return Return the quote if the string enclosed width quote.
	 */
	public static String removeQuote(String string) {
		if (string != null && string.length() >= 2 && string.startsWith("\"") //$NON-NLS-1$
				&& string.endsWith("\"")) //$NON-NLS-1$
		{
			return string.substring(1, string.length() - 1);
		}
		return string;
	}

	/**
	 * Gets the meta data dictionary of model
	 *
	 * @return the meta data dictionary
	 */
	public static IMetaDataDictionary getMetaDataDictionary() {
		return designEngine.getMetaData();
	}

	/**
	 * Convert date string to xml string
	 *
	 * @param date date to be converted
	 * @return Return the converted string
	 */
	public static String convertToXMLString(Date date) {
		if (date == null) {
			return null;
		}
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(date);
		String pattern = XMLDATE_PATTERN_FULL;
		if (!cal.isSet(Calendar.HOUR)) {
			pattern = XMLDATE_PATTERN_DATE_ONLY;
		} else if (!cal.isSet(Calendar.SECOND)) {
			pattern = XMLDATE_PATTERN_WITH_OUT_SECOND;
		} else if (!cal.isSet(Calendar.MILLISECOND)) {
			pattern = XMLDATE_PATTERN_WITH_OUT_MILLISECOND;
		}
		DateFormatter formater = new DateFormatter(pattern);
		return formater.format(date);
	}

	/**
	 * Convert the xml date to string
	 *
	 * @param xmlString xml date string
	 * @return Return the converted string
	 * @throws ParseException
	 */
	public static Date convertToDate(String xmlString) throws ParseException {
		if (StringUtil.isBlank(xmlString)) {
			return null;
		}
		String pattern = null;
		if (xmlString.indexOf('T') != -1) {
			if (xmlString.indexOf('.') != -1) {
				pattern = XMLDATE_PATTERN_FULL;
			} else if (xmlString.indexOf(':') == xmlString.lastIndexOf(':')) {
				pattern = XMLDATE_PATTERN_WITH_OUT_SECOND;
			} else {
				pattern = XMLDATE_PATTERN_WITH_OUT_MILLISECOND;
			}
		} else {
			pattern = XMLDATE_PATTERN_DATE_ONLY;
		}
		DateFormatter formater = new DateFormatter(pattern);
		return formater.parse(xmlString);
	}

	/**
	 * Get the input size
	 *
	 * @param input design element
	 * @return Return the input size
	 */
	public static int getInputSize(Object input) {
		if (input instanceof GroupElementHandle) {
			return ((GroupElementHandle) input).getElements().size();
		} else if (input instanceof List) {
			return (getMultiSelectionHandle((List<?>) input)).getElements().size();
		}
		return -1;
	}

	/**
	 * Get the first element of the input element
	 *
	 * @param input design element
	 * @return Return the first element of the input element
	 */
	public static Object getInputFirstElement(Object input) {
		if (input instanceof GroupElementHandle) {
			return ((GroupElementHandle) input).getElements().get(0);
		} else if (input instanceof List) {
			return ((List<?>) input).get(0);
		}
		return input;
	}

	/**
	 * Get the first element of the input element
	 *
	 * @param input   design element
	 * @param notSame without the same element
	 * @return Return the first element of the input element
	 */
	public static Object getInputFirstElement(Object input, boolean notSame) {
		if (input instanceof GroupElementHandle) {
			if (notSame && ((GroupElementHandle) input).isSameType()) {
				return null;
			}
			return ((GroupElementHandle) input).getElements().get(0);
		} else if (input instanceof List) {
			GroupElementHandle group = DEUtil.getGroupElementHandle((List<?>) input);
			if (notSame && group != null && group.isSameType()) {
				return null;
			}
			return ((List<?>) input).get(0);
		}
		return input;
	}

	/**
	 * Get the input element
	 *
	 * @param input input elements
	 * @param index index of element
	 * @return Return the input element
	 */
	public static Object getInputElement(Object input, int index) {
		if (input instanceof GroupElementHandle) {
			return ((GroupElementHandle) input).getElements().get(index);
		} else if (input instanceof List) {
			return ((List<?>) input).get(index);
		}
		return input;
	}

	/**
	 * Get an input element list
	 *
	 * @param input input elements
	 * @return Return an input element list
	 */
	public static List<?> getInputElements(Object input) {
		if (input instanceof GroupElementHandle) {
			return ((GroupElementHandle) input).getElements();
		} else if (input instanceof List) {
			return (List<?>) input;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * Get the input binding
	 *
	 * @param input       report item handle
	 * @param bindingName binding name
	 * @return Return the computed column handle
	 */
	public static ComputedColumnHandle getInputBinding(ReportItemHandle input, String bindingName) {
		List<?> elementsList = DEUtil.getVisiableColumnBindingsList(input);
		if (elementsList != null && elementsList.size() > 0) {
			for (int i = 0; i < elementsList.size(); i++) {
				if (((ComputedColumnHandle) elementsList.get(i)).getName().equals(bindingName)) {
					return (ComputedColumnHandle) elementsList.get(i);
				}
			}
		}
		return null;
	}

	/**
	 * Enable row number
	 *
	 * @param parent
	 * @return row number available
	 */
	public static boolean enableRowNum(Object parent) {
		if (parent instanceof ReportItemHandle) {
			if (((ReportItemHandle) parent).getDataBindingReference() != null) {
				return enableRowNum(((ReportItemHandle) parent).getDataBindingReference());
			} else if (((ReportItemHandle) parent).getCube() != null) {
				return false;
			} else if (((ReportItemHandle) parent).getDataSet() != null) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Get the aggregate on display string
	 *
	 * @param element computed column handle
	 * @return Return the aggregate on display string
	 */
	public static String getAggregateOn(ComputedColumnHandle element) {
		List<?> aggregateOnList = element.getAggregateOnList();
		// String value = ""; //$NON-NLS-1$
		StringBuilder buffer = new StringBuilder();
		int i = 0;
		for (Iterator<?> iterator = aggregateOnList.iterator(); iterator.hasNext(); i++) {
			if (i > 0) {
				// value += ","; //$NON-NLS-1$
				buffer.append(",");
			}
			// value += (String) iterator.next( );
			buffer.append((String) iterator.next());
		}
		String value = buffer.toString();
		if (value.equals("")) { //$NON-NLS-1$
			return null;
		}
		return value;
	}

	/**
	 * Gets the hierarchy name
	 *
	 * @param object
	 * @return Return the hierarchy name
	 */
	public static String getFlatHirarchyPathName(Object object) {
		if (!(object instanceof DesignElementHandle)) {
			return null;
		}
		DesignElementHandle handle = (DesignElementHandle) object;
		DesignElementHandle container = handle.getContainer();
		String flatHirarchyName = getCombinatedName(handle);
		while (!(handle instanceof ReportDesignHandle) && container != null
				&& !(container instanceof ReportDesignHandle)) {
			SlotHandle slotHandle = handle.getContainerSlotHandle();
			if (slotHandle != null && (container instanceof ListingHandle || container instanceof GroupHandle)
					&& !(handle instanceof GroupHandle)) {
				flatHirarchyName = slotHandle.getDefn().getDisplayName() + flatHirarchyName;
			}
			flatHirarchyName = getCombinatedName(container) + "." //$NON-NLS-1$
					+ flatHirarchyName;
			handle = container;
			container = container.getContainer();
		}
		return flatHirarchyName;
	}

	private static String getCombinatedName(DesignElementHandle handle) {
		String elementName = handle.getDefn().getDisplayName();
		String displayName;
		if (handle.getQualifiedName() != null && !handle.getQualifiedName().equals(handle.getName())) {
			displayName = handle.getQualifiedName();
		} else {
			displayName = handle.getName();
		}
		if (!StringUtil.isBlank(displayName)) {
			return elementName + "(" + displayName + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		}
		return elementName + "(" + handle.getID() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Test if the handle is from library.
	 *
	 * @param handle
	 * @return Test result if the handle is from library.
	 *
	 * @deprecated use {@link #isLinkedElement(DesignElementHandle)}
	 */
	@Deprecated
	public static boolean isReferenceElement(DesignElementHandle handle) {
		return isLinkedElement(handle);
	}

	/**
	 * Get file path form of url
	 *
	 * @param url url
	 * @return Return the file path form of url
	 * @throws Exception
	 */
	public static String getFilePathFormURL(URL url) throws Exception {
		if (url != null) {
			URL localURL = FileLocator.resolve(url);
			if ("bundleresource".equals(url.getProtocol())) {
				return localURL.getPath();
			} else if (localURL != null && "file".equals(localURL.getProtocol())) {
				return localURL.toURI().getSchemeSpecificPart();
			}
		}
		return null;
	}

	/**
	 * If the layout is fix.
	 *
	 * @param model
	 * @return Verify result of fixed layout
	 */
	public static boolean isFixLayout(Object model) {
		if (!(model instanceof DesignElementHandle)) {
			return false;
		}
		ModuleHandle handle = ((DesignElementHandle) model).getModuleHandle();
		if (!(handle instanceof ReportDesignHandle)) {
			return false;
		}

		return DesignChoiceConstants.REPORT_LAYOUT_PREFERENCE_FIXED_LAYOUT
				.equals(((ReportDesignHandle) handle).getLayoutPreference());
	}

	/**
	 * Gets the padding
	 *
	 * @param handle
	 * @param retValue
	 * @return Return the padding
	 */
	public static Insets getPadding(DesignElementHandle handle, Insets retValue) {
		if (retValue == null) {
			retValue = new Insets();
		} else {
			retValue = new Insets(retValue);
		}

		int fontSize = DEUtil.getFontSizeIntValue(handle);

		DimensionValue dimensionValue = (DimensionValue) handle.getProperty(IStyleModel.PADDING_TOP_PROP);
		double px = DEUtil.convertToPixel(dimensionValue, fontSize);

		dimensionValue = (DimensionValue) handle.getProperty(IStyleModel.PADDING_BOTTOM_PROP);
		double py = DEUtil.convertToPixel(dimensionValue, fontSize);

		retValue.top = (int) px;
		retValue.bottom = (int) py;

		dimensionValue = (DimensionValue) handle.getProperty(IStyleModel.PADDING_LEFT_PROP);
		px = DEUtil.convertToPixel(dimensionValue, fontSize);

		dimensionValue = (DimensionValue) handle.getProperty(IStyleModel.PADDING_RIGHT_PROP);
		py = DEUtil.convertToPixel(dimensionValue, fontSize);

		retValue.left = (int) px;
		retValue.right = (int) py;

		return retValue;
	}

	/**
	 * Get the default library handle
	 *
	 * @return Return the default library handle
	 */
	public static LibraryHandle getDefaultLibraryHandle() {
		URL url = FileLocator.find(EclipseUtil.getBundle(IResourceLocator.FRAGMENT_RESOURCE_HOST),
				new Path(DEFAULT_LIBRARY), null);

		if (url == null) {
			return null;
		}

		String libraryFileName;
		try {
			libraryFileName = FileLocator.resolve(url).getPath();
		} catch (IOException e1) {
			return null;
		}
		File file = new File(libraryFileName);
		if (!file.exists()) {
			return null;
		}
		libraryFileName = file.getAbsolutePath();
		try {
			return SessionHandleAdapter.getInstance().getSessionHandle().openLibrary(libraryFileName);
		} catch (DesignFileException e) {
			return null;
		}
	}

	/**
	 * Sets the default theme
	 *
	 * @param elementHandle
	 */
	public static void setDefaultTheme(DesignElementHandle elementHandle) {
		// for report design we set the report level theme to the first one from
		// default library if applicable
		if (elementHandle instanceof ReportDesignHandle && hasDefaultLibrary(elementHandle.getModuleHandle())) {
			ReportDesignHandle designHandle = (ReportDesignHandle) elementHandle;
			PropertyHandle propertyHandle = designHandle.getPropertyHandle(IModuleModel.THEME_PROP);
			if (propertyHandle.getValue() == null) {
				List<?> list = propertyHandle.getReferenceableElementList();
				String preFileName = getDefultLibraryFileName();
				for (int i = 0; i < list.size(); i++) {
					ThemeHandle itemHandle = (ThemeHandle) list.get(i);
					if (itemHandle.getQualifiedName().startsWith(preFileName)) {
						try {
							propertyHandle.setValue(itemHandle.getQualifiedName());
							break;
						} catch (SemanticException e) {
							// do nothing
						}
					}
				}
			}
		}
	}

	private static String getDefultLibraryFileName() {
		LibraryHandle defaulthandle = getDefaultLibraryHandle();
		if (defaulthandle == null) {
			return null;
		}
		String fileName = new File(defaulthandle.getFileName()).getAbsolutePath();

		int index = fileName.lastIndexOf(".");
		int start = fileName.lastIndexOf(File.separator);
		defaulthandle.close();
		return fileName.substring(start + 1, index);
	}

	private static boolean hasDefaultLibrary(ModuleHandle handle) {
		LibraryHandle defaulthandle = getDefaultLibraryHandle();
		if (defaulthandle == null) {
			return false;
		}
		String defaultFileName = defaulthandle.getFileName();

		List<?> list = handle.getLibraries();
		for (int i = 0; i < list.size(); i++) {
			LibraryHandle temp = (LibraryHandle) list.get(i);
			String fileName = null;

			try {
				fileName = FileLocator.resolve(new URL(temp.getFileName())).getPath();
			} catch (IOException e) {

			}
			if (fileName == null) {
				continue;
			}
			if (new File(defaultFileName).getAbsolutePath().equals(new File(fileName).getAbsolutePath())) {
				defaulthandle.close();
				return true;
			}
		}
		defaulthandle.close();
		return false;
	}

	/**
	 * Reset all style properties
	 *
	 * @param handle design element handle
	 * @throws SemanticException
	 */
	public static void resetAllStyleProperties(DesignElementHandle handle) throws SemanticException {
		if (handle == null) {
			return;
		}

		Field[] fields = IStyleModel.class.getFields();
		for (int i = 0; i < fields.length; i++) {
			if ((fields[i].getModifiers() & Modifier.STATIC) != 0 && (fields[i].getModifiers() & Modifier.FINAL) != 0) {
				String propertyName = null;

				try {
					propertyName = (String) fields[i].get(IStyleModel.class);
				} catch (Exception e) {
					// ignore
				}

				if (IStyleModel.WIDTH_PROP.equals(propertyName) || IStyleModel.HEIGHT_PROP.equals(propertyName)) {
					continue;
				}

				if (propertyName != null && handle.getPropertyDefn(propertyName) != null
						&& handle.getProperty(propertyName) != null) {
					handle.setProperty(propertyName, null);
				}
			}
		}
	}
}
